package com.ruoyi.algorithm.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.algorithm.dict.entity.Dictionary;
import com.ruoyi.algorithm.dict.repository.DictionaryRepository;
import com.ruoyi.algorithm.entity.Algorithm;
import com.ruoyi.algorithm.entity.AlgorithmHistory;
import com.ruoyi.algorithm.entity.Manufacturer;
import com.ruoyi.algorithm.entity.Operator;
import com.ruoyi.algorithm.model.ManufacturerOperatorDDBModel;
import com.ruoyi.algorithm.model.OperatorModel;
import com.ruoyi.algorithm.model.OperatorOnLineStateModel;
import com.ruoyi.algorithm.repository.*;
import com.ruoyi.algorithm.service.OperatorService;
import com.ruoyi.algorithm.util.ReflectionUtil;
import com.beihu.sightplus.common.authorization.service.UserAuthorization;
import com.beihu.sightplus.common.response.PageResult;
import com.beihu.sightplus.common.response.PageUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class OperatorServiceImpl implements OperatorService {

    @Autowired
    private OperatorRepository operatorRepository;

    @Autowired
    private OperatorVersionRepository operatorVersionRepository;

    @Autowired
    private ManufacturerRepository manufacturerRepository;

    @Autowired
    private AlgorithmRepository algorithmRepository;

    @Autowired
    private AlgorithmHistoryRepository algorithmHistoryRepository;

    @Autowired
    private DictionaryRepository dictionaryRepository;

    /**
     * 新增
     */
    public void add(Operator operator) {
        // 设置默认值
        operator.setIsOnline("0");  // 在线标志（0:下线；1：上线）
        operator.setCreateTime(new Date());  // 创建时间
        operator.setUpdateTime(new Date());  // 更新时间
        operator.setCreateUser(UserAuthorization.getUserAuthorization().getId());  // 创建人
        operator.setDelFlag("0");  // 删除标志（0未删除；1已删除）

        operatorRepository.save(operator);
    }

    /**
     * 修改
     */
    public void update(Operator operator) {
        operator.setUpdateTime(new Date());
        operator.setUpdateUser(2L);
        operatorRepository.updateById(operator);
    }

    /**
     * 删除
     */
    public int delete(Long operatorId) {
        int deleteCount = 0;
        // 查询有没有被算子版本关联
        Boolean isBind = operatorVersionRepository.isBindOperator(operatorId);

        // 有则不能删除,无则可以删除
        if (isBind) {
            Operator operator = new Operator();
            operator.setId(operatorId);
            operator.setDelFlag("1");
            operatorRepository.updateById(operator);

            deleteCount = 1;
        }

        return deleteCount;
    }

    /**
     * 上下线
     */
    public void setOnlineState(OperatorOnLineStateModel operatorOnLineStateModel) {
        Operator operator = new Operator();
        operator.setId(operatorOnLineStateModel.getOperatorId());
        operator.setIsOnline(operatorOnLineStateModel.getOptionType());

        operatorRepository.updateById(operator);
    }

    /**
     * 查询算子详情信息
     */
    public OperatorModel detail(Long operatorId) {
        Operator operator = operatorRepository.getById(operatorId);

        // 将【Operator】对象转换成【OperatorModel】对象
        OperatorModel operatorModel = this.convertFromOperator(operator);
        return operatorModel;
    }


    /**
     * 分页操作
     * orderAttr【排序字段】
     * orderType【排序方式，升序还是降序】
     * current【当前页码】
     * size【每页展示的数量】
     */
    public PageResult pageList(String orderAttr, String orderType, Long current, Long size, OperatorModel operatorModel) {
        // 1.处理动态查询条件
        Map map = JSONObject.parseObject(JSON.toJSONString(operatorModel), Map.class);
        Set keySet = map.keySet();

        List<Map<String, Object>> conditionList = new ArrayList<>();

        //该列表添加带有查询条件专用注解的类，如有继承关系可单独添加子类
        List<Class<?>> clazzList = new ArrayList<>();
        clazzList.add(OperatorModel.class);

        for (Object keyObject : keySet) {
            String key = keyObject.toString();

            String conditionKey = ReflectionUtil.getTableFieldValue(clazzList, key);
            if (conditionKey == null) {
                continue;
            }
            Map<String, Object> conditionMap = new HashMap<>();
            conditionMap.put("conditionKey", conditionKey);
            conditionMap.put("conditionValue", map.get(key));

            // 从属性上获取匹配符号
            String matchType = ReflectionUtil.getTableFieldMatchType(operatorModel.getClass(), key);

            if (matchType.contains("LIKE")) {
                conditionMap.put("conditionMatchType", 1);
            } else {
                conditionMap.put("conditionMatchType", 0);
            }

            conditionList.add(conditionMap);
        }

        // 3.将排序的表字段作为方法的输入参数，写查询sql
        Page<OperatorModel> page = operatorRepository.listByPage(conditionList, ReflectionUtil.getTableFieldValue(clazzList, orderAttr), orderType, current, size);
        return PageUtils.getPageResult(page);
    }


    @Override
    public Operator findByOperatorVersion(Long operatorVersionId) {
        return operatorRepository.getOne(Wrappers.lambdaQuery(Operator.class).eq(Operator::getOperatorVersionId, operatorVersionId));
    }

    /**
     * 将【Operator】对象转换成【OperatorModel】对象
     */
    public OperatorModel convertFromOperator(Operator operator) {
        OperatorModel operatorModel = new OperatorModel();
        BeanUtils.copyProperties(operator, operatorModel);

        // 获取厂商名称
        Manufacturer manufacturer = manufacturerRepository.getById(operator.getManufacturerId());
        operatorModel.setManufacturerName(manufacturer == null || manufacturer.getName() == null ? "" : manufacturer.getName());

        // 获取协议类型（从字典表中获取）
        operatorModel.setAgreementType(this.getAgreementType(operator.getAgreementTypeId()));

        // 获取部门名称
        operatorModel.setDeptName(this.getDeptName(operator.getDepartmentId()));

        // 获取算法类型（从字典表中获取）
        operatorModel.setAlgorithmType(this.getAgreementType(operator.getAlgorithmTypeId()));
        return operatorModel;
    }

    /**
     * 查询厂商和算子信息，支持根据算子名称
     */
    public List<ManufacturerOperatorDDBModel> getManufacturerOperatorDDB(String operatorName) {
        return operatorRepository.getManufacturerOperatorDDB(operatorName);
    }


    /**
     * 切换算法绑定的算子版本号
     */
    public void changeBindingOperatorVersion(Long operatorId, Long operatorVersionId) {
        // 1.根据算子Id查询算法信息
        List<Algorithm> orgAlgorithmList = algorithmRepository.getByOperatorId(operatorId);

        // 2.根据算子Id,算法Id和算子版本号Id到算法历史表中查询算法历史数据
        for (Algorithm orgAlgorithm : orgAlgorithmList) {
            AlgorithmHistory orgAlgorithmHistory = algorithmHistoryRepository.getByAlgorithmIdOperatorIdAndOperatorVersionId(orgAlgorithm.getId(), operatorId, operatorVersionId);

            // 3.若没有，则将数据新增到算法历史数据中
            if (orgAlgorithmHistory == null){
                AlgorithmHistory algorithmHistory = new AlgorithmHistory();
                BeanUtils.copyProperties(orgAlgorithm, algorithmHistory);
                algorithmHistory.setAlgorithmId(orgAlgorithm.getId());
                algorithmHistory.setOperatorVersionId(operatorVersionId);
                algorithmHistory.setId(null);
                algorithmHistoryRepository.save(algorithmHistory);
            } else {
                Algorithm algorithm = new Algorithm();
                BeanUtils.copyProperties(orgAlgorithmHistory, algorithm);
                algorithm.setId(orgAlgorithmHistory.getAlgorithmId());
                algorithmRepository.updateById(algorithm);
            }
        }

        // 5.修改算子表中的算子版本字段信息
        Operator operator = new Operator();
        operator.setId(operatorId);
        operator.setOperatorVersionId(operatorVersionId);
        operatorRepository.updateById(operator);
    }

    /**
     * 获取协议类型(从数据字典中获取)
     */
    public String getAgreementType(Long dictionaryId){
        Dictionary dictionary = dictionaryRepository.getById(dictionaryId);
        return dictionary.getValue();
    }

    /**
     * 获取部门名称
     */
    public String getDeptName(Long deptId){
        return "消防部";
    }

}
